// firmware-a7/drivers/ipc-gateway/ipc_gateway_driver.c

#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/rpmsg.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <linux/wait.h>
#include <linux/spinlock.h>
#include <linux/uaccess.h>
#include <linux/atomic.h>

#define IPC_DEVICE_NAME    "mbus_gateway"
#define IPC_BUFFER_SIZE    1024
#define MAX_RX_MESSAGES    32

// 接收消息结构
struct mbus_rx_message {
    struct list_head list;
    size_t len;
    uint8_t data[0];
};

// 主设备数据结构
struct mbus_gateway_dev {
    struct miscdevice miscdev;
    struct rpmsg_device *rpdev;
    
    // 接收消息队列
    struct list_head rx_queue;
    spinlock_t rx_lock;
    wait_queue_head_t rx_waitq;
    int rx_queue_count;
    
    // 统计信息
    atomic_t messages_sent;
    atomic_t messages_received;
    atomic_t rx_errors;
    atomic_t tx_errors;
    
    // 设备状态
    bool device_ready;
    struct completion link_ready;
};

// 全局设备实例
static struct mbus_gateway_dev *mbus_dev;

static int mbus_gateway_open(struct inode *inode, struct file *filp)
{
    struct mbus_gateway_dev *dev = container_of(filp->private_data,
                                               struct mbus_gateway_dev,
                                               miscdev);
    
    filp->private_data = dev;
    
    // 等待设备就绪（如果正在初始化）
    if (!dev->device_ready) {
        if (wait_for_completion_interruptible(&dev->link_ready))
            return -ERESTARTSYS;
    }
    
    return 0;
}

static int mbus_gateway_release(struct inode *inode, struct file *filp)
{
    return 0;
}

static ssize_t mbus_gateway_read(struct file *filp, char __user *buf,
                                size_t count, loff_t *f_pos)
{
    struct mbus_gateway_dev *dev = filp->private_data;
    struct mbus_rx_message *msg;
    ssize_t retval = 0;
    unsigned long flags;
    
    // 非阻塞模式检查
    if (filp->f_flags & O_NONBLOCK) {
        spin_lock_irqsave(&dev->rx_lock, flags);
        if (list_empty(&dev->rx_queue)) {
            spin_unlock_irqrestore(&dev->rx_lock, flags);
            return -EAGAIN;
        }
        spin_unlock_irqrestore(&dev->rx_lock, flags);
    }
    
    // 等待消息到达
    if (wait_event_interruptible(dev->rx_waitq,
                                !list_empty(&dev->rx_queue)))
        return -ERESTARTSYS;
    
    spin_lock_irqsave(&dev->rx_lock, flags);
    
    if (list_empty(&dev->rx_queue)) {
        spin_unlock_irqrestore(&dev->rx_lock, flags);
        return 0;
    }
    
    // 获取队列中的第一个消息
    msg = list_first_entry(&dev->rx_queue, struct mbus_rx_message, list);
    
    // 检查用户缓冲区是否足够
    if (count < msg->len) {
        spin_unlock_irqrestore(&dev->rx_lock, flags);
        return -EMSGSIZE;
    }
    
    // 拷贝数据到用户空间
    if (copy_to_user(buf, msg->data, msg->len)) {
        spin_unlock_irqrestore(&dev->rx_lock, flags);
        return -EFAULT;
    }
    
    // 从队列中移除并释放
    list_del(&msg->list);
    dev->rx_queue_count--;
    spin_unlock_irqrestore(&dev->rx_lock, flags);
    
    retval = msg->len;
    kfree(msg);
    
    return retval;
}

static ssize_t mbus_gateway_write(struct file *filp, const char __user *buf,
                                 size_t count, loff_t *f_pos)
{
    struct mbus_gateway_dev *dev = filp->private_data;
    void *kbuf;
    int ret;
    
    if (!dev->device_ready || !dev->rpdev)
        return -ENODEV;
    
    if (count == 0)
        return 0;
        
    if (count > IPC_BUFFER_SIZE)
        return -EMSGSIZE;
    
    // 分配内核缓冲区
    kbuf = kmalloc(count, GFP_KERNEL);
    if (!kbuf)
        return -ENOMEM;
    
    // 从用户空间拷贝数据
    if (copy_from_user(kbuf, buf, count)) {
        kfree(kbuf);
        return -EFAULT;
    }
    
    // 通过RPMSG发送到M4
    ret = rpmsg_send(dev->rpdev->ept, kbuf, count);
    kfree(kbuf);
    
    if (ret) {
        atomic_inc(&dev->tx_errors);
        dev_err(&dev->rpdev->dev, "rpmsg_send failed: %d\n", ret);
        return ret;
    }
    
    atomic_inc(&dev->messages_sent);
    return count;
}

static __poll_t mbus_gateway_poll(struct file *filp, poll_table *wait)
{
    struct mbus_gateway_dev *dev = filp->private_data;
    __poll_t mask = 0;
    unsigned long flags;
    
    poll_wait(filp, &dev->rx_waitq, wait);
    
    spin_lock_irqsave(&dev->rx_lock, flags);
    
    // 检查是否有数据可读
    if (!list_empty(&dev->rx_queue))
        mask |= EPOLLIN | EPOLLRDNORM;
    
    // 检查是否可写（设备就绪）
    if (dev->device_ready && dev->rpdev)
        mask |= EPOLLOUT | EPOLLWRNORM;
    else
        mask |= EPOLLHUP;
        
    spin_unlock_irqrestore(&dev->rx_lock, flags);
    
    return mask;
}

// 文件操作结构
static const struct file_operations mbus_gateway_fops = {
    .owner = THIS_MODULE,
    .open = mbus_gateway_open,
    .release = mbus_gateway_release,
    .read = mbus_gateway_read,
    .write = mbus_gateway_write,
    .poll = mbus_gateway_poll,
    .llseek = no_llseek,
};

// Misc设备定义
static struct miscdevice mbus_gateway_miscdev = {
    .minor = MISC_DYNAMIC_MINOR,
    .name = IPC_DEVICE_NAME,
    .fops = &mbus_gateway_fops,
    .mode = 0666,
};

static int mbus_gateway_rpmsg_callback(struct rpmsg_device *rpdev, void *data,
                                      int len, void *priv, u32 src)
{
    struct mbus_gateway_dev *dev = dev_get_drvdata(&rpdev->dev);
    struct mbus_rx_message *msg;
    unsigned long flags;
    
    if (!dev || !data || len <= 0) {
        if (dev)
            atomic_inc(&dev->rx_errors);
        return -EINVAL;
    }
    
    // 限制消息长度
    if (len > IPC_BUFFER_SIZE) {
        dev_warn(&rpdev->dev, "Received oversized message: %d bytes\n", len);
        if (dev)
            atomic_inc(&dev->rx_errors);
        return -EMSGSIZE;
    }
    
    // 分配消息结构
    msg = kmalloc(sizeof(*msg) + len, GFP_ATOMIC);
    if (!msg) {
        if (dev)
            atomic_inc(&dev->rx_errors);
        return -ENOMEM;
    }
    
    msg->len = len;
    memcpy(msg->data, data, len);
    
    // 添加到接收队列
    spin_lock_irqsave(&dev->rx_lock, flags);
    
    // 检查队列是否已满
    if (dev->rx_queue_count >= MAX_RX_MESSAGES) {
        // 丢弃最旧的消息
        struct mbus_rx_message *old_msg = list_first_entry(&dev->rx_queue,
                                                          struct mbus_rx_message,
                                                          list);
        list_del(&old_msg->list);
        kfree(old_msg);
        dev->rx_queue_count--;
        dev_warn(&rpdev->dev, "RX queue full, dropped oldest message\n");
    }
    
    list_add_tail(&msg->list, &dev->rx_queue);
    dev->rx_queue_count++;
    spin_unlock_irqrestore(&dev->rx_lock, flags);
    
    // 唤醒等待的读取进程
    wake_up_interruptible(&dev->rx_waitq);
    
    atomic_inc(&dev->messages_received);
    
    return 0;
}

static void mbus_gateway_rpmsg_remove(struct rpmsg_device *rpdev)
{
    struct mbus_gateway_dev *dev = dev_get_drvdata(&rpdev->dev);
    struct mbus_rx_message *msg, *tmp;
    unsigned long flags;
    
    dev_info(&rpdev->dev, "RPMSG device removed\n");
    
    if (dev) {
        dev->device_ready = false;
        dev->rpdev = NULL;
        
        // 清空接收队列
        spin_lock_irqsave(&dev->rx_lock, flags);
        list_for_each_entry_safe(msg, tmp, &dev->rx_queue, list) {
            list_del(&msg->list);
            kfree(msg);
        }
        dev->rx_queue_count = 0;
        spin_unlock_irqrestore(&dev->rx_lock, flags);
        
        // 唤醒所有等待的进程
        wake_up_interruptible(&dev->rx_waitq);
    }
}

static int mbus_gateway_rpmsg_probe(struct rpmsg_device *rpdev)
{
    struct mbus_gateway_dev *dev;
    int ret;
    
    dev_info(&rpdev->dev, "RPMSG-MBUS device probed: %s\n", rpdev->id.name);
    
    // 分配主设备结构
    dev = kzalloc(sizeof(*dev), GFP_KERNEL);
    if (!dev)
        return -ENOMEM;
    
    // 初始化设备结构
    INIT_LIST_HEAD(&dev->rx_queue);
    spin_lock_init(&dev->rx_lock);
    init_waitqueue_head(&dev->rx_waitq);
    init_completion(&dev->link_ready);
    dev->rx_queue_count = 0;
    
    dev->rpdev = rpdev;
    dev_set_drvdata(&rpdev->dev, dev);
    
    // 注册Misc设备
    mbus_gateway_miscdev.parent = &rpdev->dev;
    ret = misc_register(&mbus_gateway_miscdev);
    if (ret) {
        dev_err(&rpdev->dev, "Failed to register misc device: %d\n", ret);
        kfree(dev);
        return ret;
    }
    
    mbus_dev = dev;
    dev->device_ready = true;
    complete(&dev->link_ready);
    
    dev_info(&rpdev->dev, "MBUS Gateway driver probed successfully\n");
    return 0;
}

static struct rpmsg_device_id mbus_gateway_rpmsg_id_table[] = {
    { .name = "rpmsg-mbus" },  // 修改为 rpmsg-mbus
    { },
};

static struct rpmsg_driver mbus_gateway_rpmsg_driver = {
    .drv.name = KBUILD_MODNAME,
    .id_table = mbus_gateway_rpmsg_id_table,
    .probe = mbus_gateway_rpmsg_probe,
    .remove = mbus_gateway_rpmsg_remove,
    .callback = mbus_gateway_rpmsg_callback,
};

static int __init mbus_gateway_init(void)
{
    int ret;
    
    pr_info("MBUS Gateway driver initializing\n");
    
    ret = register_rpmsg_driver(&mbus_gateway_rpmsg_driver);
    if (ret) {
        pr_err("Failed to register RPMSG driver: %d\n", ret);
        return ret;
    }
    
    pr_info("MBUS Gateway driver initialized successfully\n");
    return 0;
}

static void __exit mbus_gateway_exit(void)
{
    unregister_rpmsg_driver(&mbus_gateway_rpmsg_driver);
    
    if (mbus_dev) {
        // 清理接收队列
        struct mbus_rx_message *msg, *tmp;
        unsigned long flags;
        misc_deregister(&mbus_gateway_miscdev);
        spin_lock_irqsave(&mbus_dev->rx_lock, flags);
        list_for_each_entry_safe(msg, tmp, &mbus_dev->rx_queue, list) {
            list_del(&msg->list);
            kfree(msg);
        }
        spin_unlock_irqrestore(&mbus_dev->rx_lock, flags);
        
        kfree(mbus_dev);
        mbus_dev = NULL;
    }
    
    pr_info("MBUS Gateway driver unloaded\n");
}

module_init(mbus_gateway_init);
module_exit(mbus_gateway_exit);

MODULE_DESCRIPTION("STM32MP157 MBUS Gateway Driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("HQYJ");
MODULE_DEVICE_TABLE(rpmsg, mbus_gateway_rpmsg_id_table);
